/* Orbas:
 *     A open source CORBA Specification implementation from Huihoo.
 *
 * Copyright 2002-2003 Huihoo.org, Inc. All Right Reserved.
 *
 * This software is licensed under LGPL license.
 * See terms of license at gnu.org.
 *
 * For more information, visit:
 *
 * http://www.huihoo.org/orbas
 */


package org.huihoo.orbas.poa;

/**
 * <p>Description: </p>
 * POA Implement of CORBA POA.
 * <p>Copyright (c) 2003</p>
 * <p>Company: <a href="http://www.huihoo.org/orbas">huihoo.org</a></p>
 * @author <a href="http://www.huihoo.org/~cocia">Cocia Lin(cocia@163.com)</a>
 * @see <a href="http://www.huihoo.org/orbas">http://www.huihoo.org/orbas</a>
 * @version 1.0
 */

import com.cognition.util.j2me.Logger;
import com.cognition.util.j2me.SystemLogger;
import com.cognition.util.marshal.JavaPrimitiveInputStream;
import com.cognition.util.marshal.JavaPrimitiveOutputStream;
import java.io.IOException;
import java.util.*;

import org.huihoo.orbas.orb.ORB;
import org.huihoo.orbas.orb.ior.*;
import org.huihoo.orbas.poa.*;
import org.omg.CORBA.*;
import org.omg.CORBA.Object;
import org.omg.CORBA.portable.*;
import org.omg.PortableServer.*;
import org.huihoo.orbas.poa.policy.*;
import org.huihoo.orbas.poa.util.*;
public class POAImpl
    extends org.omg.CORBA.LocalObject
    implements POA, OrbasPoa {
    //~
    //the_name()
    private String name;
    //the_children()
    private Hashtable children = new Hashtable();
    //the_parent()
    private org.omg.PortableServer.POA parent;
    //the_POAManager()
    private POAManager poaManager;
    //the orbas orb instance
    private org.huihoo.orbas.orb.ORB orb;
    //policies attribute var
    //private IdAssignmentPolicy idAssignmentPolicy;
    private boolean system_id = true; //new poa default.
    private boolean user_id = false;
    //private IdUniquenessPolicy idUniquenessPolicy;
    private boolean unique_id = true; //new poa default.
    private boolean multiple_id = false;
    //private ImplicitActivationPolicy implicitActivationPolicy;
    private boolean implicit_activation = false;
    private boolean no_implicit_activation = true; //new poa default.
    //private LifespanPolicy lifespanPolicy;
    private boolean _transient = true; //new poa default.
    private boolean persistent = false;
    //private RequestProcessingPolicy requestProcessingPolicy;
    private boolean use_active_object_map_only = true; //new poa default.
    private boolean use_default_servant = false;
    private boolean use_servant_manager = false;
    //private ServantRetentionPolicy servantRetentionPolicy;
    private boolean retain = true; //new poa default.
    private boolean non_retain = false;
    //private ThreadPolicy threadPolicy;
    private boolean orb_ctrl_model = true; //new poa default.
    private boolean single_thread_model = false;
    private boolean main_thread_model = false; //corba 2.3 later

    //policies attribute end

    //active servant object map(aom)
    //ActiveObjectMap aom = new ActiveObjectMap();
    java.util.Hashtable aom = new java.util.Hashtable();
    java.util.Hashtable aomReverse = new java.util.Hashtable();
    //poa's id for orb's poa map
    private byte[] id;
    //Logger tool.
    private static Logger logger = SystemLogger.getLogger(SystemLogger.LOGGER_CONSOLE);
    public static final String LOG_TAG = "POAImpl";
    //
    public POAImpl() {
        logger.debug(LOG_TAG, "<init>s");
        /*Common Object Request Broker Architecture (CORBA), v3.0 July 2002
         (page 11-6)
         The root POA has the following policies.
         \u2022 Thread Policy: ORB_CTRL_MODEL
         \u2022 Lifespan Policy: TRANSIENT
         \u2022 Object Id Uniqueness Policy: UNIQUE_ID
         \u2022 Id Assignment Policy: SYSTEM_ID
         \u2022 Servant Retention Policy: RETAIN
         \u2022 Request Processing Policy: USE_ACTIVE_OBJECT_MAP_ONLY
         \u2022 Implicit Activation Policy: IMPLICIT_ACTIVATION
         */
        //create default policies for RootPOA
        Policy threadPolicy = create_thread_policy(
            org.omg.PortableServer.ThreadPolicyValue.ORB_CTRL_MODEL);
        Policy lifespanPolicy = create_lifespan_policy(
            org.omg.PortableServer.LifespanPolicyValue.TRANSIENT);
        Policy idUniquenessPolicy = create_id_uniqueness_policy(
            org.omg.PortableServer.IdUniquenessPolicyValue.UNIQUE_ID);
        Policy idAssignmentPolicy = create_id_assignment_policy(
            org.omg.PortableServer.IdAssignmentPolicyValue.SYSTEM_ID);
        Policy implicitActivationPolicy = create_implicit_activation_policy(
            org.omg.PortableServer.ImplicitActivationPolicyValue.
            IMPLICIT_ACTIVATION);
        Policy servantRetentionPolicy = create_servant_retention_policy(
            org.omg.PortableServer.ServantRetentionPolicyValue.RETAIN);
        Policy requestProcessingPolicy = create_request_processing_policy(
            org.omg.PortableServer.RequestProcessingPolicyValue.
            USE_ACTIVE_OBJECT_MAP_ONLY);

        Policy[] policies = new Policy[7];
        policies[0] = threadPolicy;
        policies[1] = lifespanPolicy;
        policies[2] = idUniquenessPolicy;
        policies[3] = idAssignmentPolicy;
        policies[4] = implicitActivationPolicy;
        policies[5] = servantRetentionPolicy;
        policies[6] = requestProcessingPolicy;

        initPOA(null, this, "RootPOA", new POAManagerImpl(), policies);

    }

    public POAImpl(ORB orb, POA parent, String adapter_name,
                   POAManager a_POAManager,
                   Policy[] policies) {
        logger.debug(LOG_TAG, "POAImpl(...)");
        initPOA(orb, parent, adapter_name, a_POAManager, policies);

    }

    protected void initPOA(ORB orb, POA parent, String adapter_name,
                           POAManager a_POAManager,
                           Policy[] policies) {
        logger.debug(LOG_TAG, "initPOA(" + adapter_name + ")");
        //if POAManager is empty then create a new one,
        //else set it for the new POA
        if (a_POAManager == null) {
            a_POAManager = new POAManagerImpl();
        }
        this.poaManager = a_POAManager;
        //save policies setting
        for (int i = 0; i < policies.length; i++) {
            switch (policies[i].policy_type()) {
                case org.omg.PortableServer.THREAD_POLICY_ID.value:
                    if ( ( (ThreadPolicy) policies[i]).value().value() ==
                        ThreadPolicyValue._ORB_CTRL_MODEL) {
                        orb_ctrl_model = true; //true
                        single_thread_model = false;
                        main_thread_model = false;
                    }
                    else if ( ( (ThreadPolicy) policies[i]).value().value() ==
                             ThreadPolicyValue._SINGLE_THREAD_MODEL) {
                        orb_ctrl_model = false;
                        single_thread_model = true; //true
                        main_thread_model = false;

                    }
                    else {
                        orb_ctrl_model = false;
                        single_thread_model = false;
                        main_thread_model = true; //true
                    }
                    break;
                case org.omg.PortableServer.LIFESPAN_POLICY_ID.value:
                    if ( ( (LifespanPolicy) policies[i]).value().value() ==
                        LifespanPolicyValue._TRANSIENT) {
                        _transient = true;
                        persistent = false;
                    }
                    else {
                        _transient = false;
                        persistent = true;
                    }
                    break;
                case org.omg.PortableServer.ID_UNIQUENESS_POLICY_ID.value:
                    if ( ( (IdUniquenessPolicy) policies[i]).value().value() ==
                        IdUniquenessPolicyValue._UNIQUE_ID) {
                        unique_id = true;
                        multiple_id = false;
                    }
                    else {
                        unique_id = false;
                        multiple_id = true;
                    }
                    break;
                case org.omg.PortableServer.ID_ASSIGNMENT_POLICY_ID.value:
                    if ( ( (IdAssignmentPolicy) policies[i]).value().value() ==
                        IdAssignmentPolicyValue._SYSTEM_ID) {
                        system_id = true;
                        user_id = false;
                    }
                    else {
                        system_id = false;
                        user_id = true;
                    }
                    break;
                case org.omg.PortableServer.IMPLICIT_ACTIVATION_POLICY_ID.value:
                    if ( ( (ImplicitActivationPolicy) policies[i]).value().
                        value() ==
                        ImplicitActivationPolicyValue._NO_IMPLICIT_ACTIVATION) {
                        no_implicit_activation = true;
                        implicit_activation = false;
                    }
                    else {
                        no_implicit_activation = false;
                        implicit_activation = true;
                    }
                    break;
                case org.omg.PortableServer.SERVANT_RETENTION_POLICY_ID.value:
                    if ( ( (ServantRetentionPolicy) policies[i]).value().value() ==
                        ServantRetentionPolicyValue._RETAIN) {
                        retain = true;
                        non_retain = false;
                    }
                    else {
                        retain = false;
                        non_retain = true;
                    }
                    break;
                case org.omg.PortableServer.REQUEST_PROCESSING_POLICY_ID.value:
                    if ( ( (RequestProcessingPolicy) policies[i]).value().value() ==
                        RequestProcessingPolicyValue.
                        _USE_ACTIVE_OBJECT_MAP_ONLY) {
                        use_active_object_map_only = true;
                        use_default_servant = false;
                        use_servant_manager = false;
                    }
                    else if ( ( (RequestProcessingPolicy) policies[i]).value().
                             value() ==
                             RequestProcessingPolicyValue._USE_DEFAULT_SERVANT) {
                        use_active_object_map_only = false;
                        use_default_servant = true;
                        use_servant_manager = false;

                    }

                    else {
                        use_active_object_map_only = false;
                        use_default_servant = false;
                        use_servant_manager = true;

                    }
                    break;
                default:
                    //error policy.
            }
        }
        //set parent POA
        this.parent = parent;
        //set name
        this.name = adapter_name;
        //generate id for poa
        this.id = UniqueIdGenerator.generateId().getBytes();
        //set the orb
        this.orb = orb;

    }

    public POA create_POA(String adapter_name, POAManager a_POAManager,
                          Policy[] policies) throws org.omg.PortableServer.
        POAPackage.AdapterAlreadyExists,
        org.omg.PortableServer.POAPackage.InvalidPolicy {
        //check policies first:
        //must not contain the wrong policy in array policies
        int[] policyType = new int[policies.length];
        for (int i = 0; i < policyType.length; i++) {
            policyType[i] = policies[i].policy_type();
        }
        //check for duplicate policy
        for (int i = 0; i < policyType.length; i++) {
            for (int j = 0; j < policyType.length; j++) {
                if (i != j && policyType[i] == policyType[j]) {
                    throw new org.omg.PortableServer.POAPackage.InvalidPolicy();
                }
            }
        }

        //check:must not have same poa in the_children()
        if (children.containsKey(adapter_name)) {
            throw new org.omg.PortableServer.POAPackage.
                AdapterAlreadyExists("POA name:" + adapter_name +
                                     " already exist in its parent POA:" +
                                     the_name());
        }

        //create new POA
        return new POAImpl(orb, this, adapter_name, a_POAManager, policies);
    }

    public POA find_POA(String adapter_name, boolean activate_it) throws org.
        omg.PortableServer.POAPackage.AdapterNonExistent {
        //check for the poa exist
        synchronized (children) {
            if (children.containsKey(adapter_name)) {
                return (POA) children.get(adapter_name);
            }

            //handle for poa not exist
            //1.get AdapterActivator and active a poa
            //2.if not AdapterActivator then throw exception
            //here is minimum corba,so no AdapterActivator support.
            throw new org.omg.PortableServer.POAPackage.AdapterNonExistent(
                "POA[name:" + adapter_name + "] not exist.");
        }

    }

    public void destroy(boolean etherealize_objects,
                        boolean wait_for_completion) {
        /**@todo Implement this org.omg.PortableServer.POAOperations method*/
        throw new java.lang.UnsupportedOperationException(
            "Method destroy() not yet implemented.");
    }

    /**
     * Minimum CORBA:Method create_thread_policy() not yet implemented.
     * @param value
     * @return ThreadPolicy
     */
    public ThreadPolicy create_thread_policy(ThreadPolicyValue value) {
        return new ThreadPolicyImpl(value);
    }

    public LifespanPolicy create_lifespan_policy(LifespanPolicyValue value) {
        return new LifespanPolicyImpl(value);
    }

    public IdUniquenessPolicy create_id_uniqueness_policy(
        IdUniquenessPolicyValue value) {
        return new IdUniquenessPolicyImpl(value);
    }

    public IdAssignmentPolicy create_id_assignment_policy(
        IdAssignmentPolicyValue value) {
        return new IdAssignmentPolicyImpl(value);
    }

    /**
         * Minimum CORBA:Method create_implicit_activation_policy() not yet implemented.
     * @param value
     * @return ImplicitActivationPolicy
     */
    public ImplicitActivationPolicy create_implicit_activation_policy(
        ImplicitActivationPolicyValue value) {
        return new ImplicitActivationPolicyImpl(value);
    }

    /**
         * Minimum CORBA:Method create_servant_retention_policy() not yet implemented.
     * @param value
     * @return ServantRetentionPolicy
     */
    public ServantRetentionPolicy create_servant_retention_policy(
        ServantRetentionPolicyValue value) {
        return new ServantRetentionPolicyImpl(value);
    }

    /**
         * Minimum CORBA:Method create_request_processing_policy() not yet implemented.
     * @param value
     * @return RequestProcessingPolicy
     */
    public RequestProcessingPolicy create_request_processing_policy(
        RequestProcessingPolicyValue value) {
        return new RequestProcessingPolicyImpl(value);
    }

    public String the_name() {
        return new String(this.name);
    }

    public POA the_parent() {
        return parent;
    }

    public POA[] the_children() {
        synchronized (children) {
            if (children == null || children.size() == 0)
                return new POA[0];

            POA[] result = new POA[children.size()];
            int i = 0;
            for (Enumeration en = children.elements(); en.hasMoreElements(); ){
                result[i++] = (POA)en.nextElement();
            }
            return result;
        }
    }

    public POAManager the_POAManager() {
        return poaManager;
    }

    public AdapterActivator the_activator() {
        throw new java.lang.UnsupportedOperationException(
            "Minimum CORBA:Method the_activator() not yet implemented.");
    }

    public void the_activator(AdapterActivator the_activator) {
        /**@todo Implement this org.omg.PortableServer.POAOperations method*/
        throw new java.lang.UnsupportedOperationException(
            "Method the_activator() not yet implemented.");
    }

    public ServantManager get_servant_manager() throws org.omg.PortableServer.
        POAPackage.WrongPolicy {
        throw new java.lang.UnsupportedOperationException(
            "Minimum CORBA:Method get_servant_manager() not yet implemented.");
    }

    public void set_servant_manager(ServantManager imgr) throws org.omg.
        PortableServer.POAPackage.WrongPolicy {
        throw new java.lang.UnsupportedOperationException(
            "Minimum CORBA:Method set_servant_manager() not yet implemented.");
    }

    public Servant get_servant() throws org.omg.PortableServer.POAPackage.
        NoServant, org.omg.PortableServer.POAPackage.WrongPolicy {
        throw new java.lang.UnsupportedOperationException(
            "Minimum CORBA:Method get_servant() not yet implemented.");
    }

    public void set_servant(Servant p_servant) throws org.omg.PortableServer.
        POAPackage.WrongPolicy {
        throw new java.lang.UnsupportedOperationException(
            "Minimum CORBA:Method set_servant() not yet implemented.");
    }

    public byte[] activate_object(Servant p_servant) throws org.omg.
        PortableServer.POAPackage.ServantAlreadyActive,
        org.omg.PortableServer.POAPackage.WrongPolicy {
        //check policy first
        if (!retain || !system_id) {
            throw new org.omg.PortableServer.POAPackage.WrongPolicy(
                "policy:RETAIN and SYSTEM_ID required.");
        }
        //if UNIQUE_ID policy exist
        //and the servent in active object map,then throw exception

        if (unique_id && aom.contains(p_servant)) {
            throw new org.omg.PortableServer.POAPackage.ServantAlreadyActive();
        }
        //generate new oid and put servant into active object map(aom)
        byte[] oid = UniqueIdGenerator.generateId().getBytes();
        ObjectKey oKey = new ObjectKey(id, oid);
        //logger.debug("Object mapping:poaid="+id+",oid="+oid+",value="+p_servant);
        aom_put(oKey.getObjectKey(), p_servant);

         //set delegate
         orb.set_delegate(p_servant);

        //Object returned
        return oid;
    }

    public void activate_object_with_id(byte[] oid, Servant p_servant) throws
        org.omg.PortableServer.POAPackage.ServantAlreadyActive,
        org.omg.PortableServer.POAPackage.ObjectAlreadyActive,
        org.omg.PortableServer.POAPackage.WrongPolicy {
        //check policy first
        if (!retain) {
            throw new org.omg.PortableServer.POAPackage.WrongPolicy(
                "policy:RETAIN required.");
        }
        //when has policy:SYSTEM_ID
        if (system_id) {
            //check oid:if it generated by system.
            //true:UniqueIdGenerator.generateId().getBytes().length == 8
            if (oid.length != 8) {
                throw new org.omg.CORBA.BAD_PARAM();
            }
        }
        //put servant into active object map(aom)
        ObjectKey oKey = new ObjectKey(this.id, oid);
        //logger.debug("Object mapping:poaid="+id+",oid="+oid+",value="+p_servant);
        aom_put(oKey.getObjectKey(), p_servant);
         //set delegate
         orb.set_delegate(p_servant);
    }

    protected void aom_put(java.lang.Object key, java.lang.Object object) {
        //put servant into active object map(aom)
        aom.put(key, object);
        //if policy unique_id==true then make a link of servent<=>oid
        if (unique_id) {
            aomReverse.put(object, key);
        }

    }

    public void deactivate_object(byte[] oid) throws org.omg.PortableServer.
        POAPackage.ObjectNotActive,
        org.omg.PortableServer.POAPackage.WrongPolicy {
        /**@todo Implement this org.omg.PortableServer.POAOperations method*/
        throw new java.lang.UnsupportedOperationException(
            "Method deactivate_object() not yet implemented.");
    }

    public Object create_reference(String intf) throws org.omg.PortableServer.
        POAPackage.WrongPolicy {
        //check policy first
        if (!system_id) {
            throw new org.omg.PortableServer.POAPackage.WrongPolicy(
                "policy:SYSTEM_ID required.");
        }
        //generate a new Object ID and create a new reference.
        byte[] oid = UniqueIdGenerator.generateId().getBytes();
        ObjectKey oKey = new ObjectKey(this.id, oid);
        IorParser parser =
            orb.createIor(oKey.getObjectKey().getBytes(), intf);

        org.omg.CORBA.Object obj = parser.getObject();

        return obj;
    }

    public Object create_reference_with_id(byte[] oid, String intf) throws org.
        omg.PortableServer.POAPackage.WrongPolicy {
        //when has policy:SYSTEM_ID
        if (system_id) {
            //check oid:if it generated by system.
            //true:UniqueIdGenerator.generateId().getBytes().length == 8
            if (oid.length != 8) {
                throw new org.omg.CORBA.BAD_PARAM();
            }
        }
        //create a new reference.
        IorParser parser =
            orb.createIor(oid, intf);
        org.omg.CORBA.Object obj = parser.getObject();
        //
        return obj;
    }

    /**
     This operation requires the USE_DEFAULT_SERVANT policy or a combination of
         the RETAIN policy and either the UNIQUE_ID or IMPLICIT_ACTIVATION policies if
     invoked outside the context of an operation dispatched by this POA. If this operation is
     not invoked in the context of executing a request on the specified servant and the policies
     specified previously are not present, the WrongPolicy exception is raised.
     This operation has four possible behaviors.
         1. If the POA has both the RETAIN and the UNIQUE_ID policy and the specified
     servant is active, the Object Id associated with that servant is returned.
         2. If the POA has both the RETAIN and the IMPLICIT_ACTIVATION policy and
     either the POA has the MULTIPLE_ID policy or the specified servant is not active,
         the servant is activated using a POA-generated Object Id and the Interface Id
     associated with the servant, and that Object Id is returned.
         3. If the POA has the USE_DEFAULT_SERVANT policy, the servant specified is the
     default servant, and the operation is being invoked in the context of executing a
         request on the default servant, then the ObjectId associated with the current
     invocation is returned.
         4. Otherwise, the ServantNotActive exception is raised.
     from 11-43
     * @param p_servant
     * @return byte[]
     * @throws org.omg.PortableServer.POAPackage.ServantNotActive
     * @throws org.omg.PortableServer.POAPackage.WrongPolicy
     */
    public byte[] servant_to_id(Servant p_servant) throws org.omg.
        PortableServer.POAPackage.ServantNotActive,
        org.omg.PortableServer.POAPackage.WrongPolicy {
        logger.debug(LOG_TAG, "servant_to_id(...)");
        //check policy first
        if (!use_default_servant
            && ! (retain && unique_id)
            && ! (retain && implicit_activation)) {
            throw new org.omg.PortableServer.POAPackage.WrongPolicy();
        }
        //handle for 4 situation
        //1)
        synchronized (aom) {
            if (unique_id && aom.contains(p_servant)) {
                //return object id
                return ( (ObjectKey) aomReverse.get(p_servant)).getObjectId();
            }
            //2)
            if (implicit_activation) {
                if (multiple_id || !aom.contains(p_servant)) {
                    //create and activate
                    byte[] oid = UniqueIdGenerator.generateId().getBytes();
                    ObjectKey oKey = new ObjectKey(this.id, oid);
//                    String[] ids = p_servant._all_interfaces(this, null);
//                    logger.debug("Object mapping:poaid="+new String(id)+",oid="+new String(oid)+",value="+p_servant+",repid "+ids[0]);
                    aom_put(oKey.getObjectKey(), p_servant);

                    //set delegate
         			orb.set_delegate(p_servant);

                    return oid;
                }
            }
        }
        //3)when has use_default_servant policy

        //4)else throw exception
        throw new org.omg.PortableServer.POAPackage.ServantNotActive();
    }

    /**
     This operation requires the RETAIN policy and either the UNIQUE_ID or
         IMPLICIT_ACTIVATION policies if invoked outside the context of an operation
     dispatched by this POA. If this operation is not invoked in the context of executing a
     request on the specified servant and the policies specified previously are not present the
     WrongPolicy exception is raised.
     This operation has four possible behaviors.
         1. If the POA has both the RETAIN and the UNIQUE_ID policy and the specified
     servant is active, an object reference encapsulating the information used to activate
     the servant is returned.
     2. If the POA has both the RETAIN and the IMPLICIT_ACTIVATION policy and
     either the POA has the MULTIPLE_ID policy or the specified servant is not active,
         the servant is activated using a POA-generated Object Id and the Interface Id
         associated with the servant, and a corresponding object reference is returned.
     3. If the operation was invoked in the context of executing a request on the specified
     servant, the reference associated with the current invocation is returned.
     4. Otherwise, the ServantNotActive exception is raised.
     from 11-43
     * @param p_servant
     * @return org.omg.CORBA.Object
     * @throws org.omg.PortableServer.POAPackage.ServantNotActive
     * @throws org.omg.PortableServer.POAPackage.WrongPolicy
     */
    public Object servant_to_reference(Servant p_servant) throws org.omg.
        PortableServer.POAPackage.ServantNotActive,
        org.omg.PortableServer.POAPackage.WrongPolicy {
        logger.debug(LOG_TAG, "servant_to_reference(" +
                p_servant.getClass().getName() + ")");
        //check policy first
        if (! (retain && unique_id)
            && ! (retain && implicit_activation)) {
            throw new org.omg.PortableServer.POAPackage.WrongPolicy();
        }
        //handle for 4 situations
        //1)
        synchronized (aom) {
            if ( (retain && unique_id)
                && aom.contains(p_servant)) {
                //create a new reference to servant
                String oKey = ( (String) aomReverse.get(p_servant));
                return servant_to_reference_with_id(oKey, p_servant);
            }

            //2)
            if ( (retain && implicit_activation)
                && (multiple_id || !aom.contains(p_servant))) {
                //create a new reference to servant
                byte[] oid = servant_to_id(p_servant);
                //byte[] oid = UniqueIdGenerator.generateId().getBytes();
                ObjectKey oKey = new ObjectKey(this.id, oid);
                //aom_put(oKey.getObjectKey(), p_servant);
                return servant_to_reference_with_id(oKey.getObjectKey(),
                    p_servant);
            }
        }
        //3)

        //4)else throw exception
        throw new org.omg.PortableServer.POAPackage.ServantNotActive();
    }

    protected org.omg.CORBA.Object servant_to_reference_with_id(String oidKey,
        Servant p_servant) {
        String[] ids = p_servant._all_interfaces(this, null);
        IorParser parser =
            orb.createIor(oidKey.getBytes(), ids[0]);

        org.omg.CORBA.Object obj = parser.getObject();

        //set delegate
        orb.set_delegate(p_servant);

        //
        return obj;

    }

    /**
         This operation requires the RETAIN policy or the USE_DEFAULT_SERVANT policy.
     If neither policy is present, the WrongPolicy exception is raised.
     If the POA has the RETAIN policy and the specified object is present in the Active
     Object Map, this operation returns the servant associated with that object in the Active
     Object Map. Otherwise, if the POA has the USE_DEFAULT_SERVANT policy and a
     default servant has been registered with the POA, this operation returns the default
     servant. Otherwise, the ObjectNotActive exception is raised.
     If the object reference was not created by this POA, the WrongAdapter exception is
     raised.
     * @param reference
     * @return org.omg.PortableServer.Servant
     * @throws org.omg.PortableServer.POAPackage.ObjectNotActive
     * @throws org.omg.PortableServer.POAPackage.WrongPolicy
     */
    public Servant reference_to_servant(Object reference) throws org.omg.
        PortableServer.POAPackage.ObjectNotActive,
        org.omg.PortableServer.POAPackage.WrongPolicy {
        logger.debug(LOG_TAG, "reference_to_servant(...)");
        //check for policy first
        //This operation requires the RETAIN policy or the USE_DEFAULT_SERVANT policy.
        if (!retain && !use_default_servant) {
            throw new org.omg.PortableServer.POAPackage.WrongPolicy();
        }
        if (retain) {
            try {
                byte[] oid = reference_to_id(reference);
                ObjectKey oKey = new ObjectKey(this.id, oid);
                synchronized (aom) {
                    if (aom.containsKey(oKey.getObjectKey())) {
                        return (Servant) aom.get(oKey.getObjectKey());
                    }
                }
            }
            catch (org.omg.PortableServer.POAPackage.WrongAdapter exwa) {
                throw new org.omg.PortableServer.POAPackage.ObjectNotActive();
            }

        } //return default servant if it exist.
        else if (use_default_servant) {
            try {
                synchronized (this) {
                    if (this.get_servant() != null) {
                        return this.get_servant();
                    }
                }

            }
            catch (org.omg.PortableServer.POAPackage.NoServant exns) {
                throw new org.omg.PortableServer.POAPackage.ObjectNotActive();
            }

        }
        //else throw exception
        throw new org.omg.PortableServer.POAPackage.ObjectNotActive();
    }

    public byte[] reference_to_id(Object reference) throws org.omg.
        PortableServer.POAPackage.WrongAdapter,
        org.omg.PortableServer.POAPackage.WrongPolicy {
        logger.debug(LOG_TAG, "reference_to_id(...)");
        org.omg.CORBA.portable.ObjectImpl objectImpl = (org.omg.CORBA.portable.
            ObjectImpl) reference;
        //
        if (objectImpl == null) {
            //report an error
            throw new org.omg.PortableServer.POAPackage.WrongAdapter(
                "POA: Not a CORBA Object.");
        }
        org.huihoo.orbas.orb.types.ObjRefDelegate delegate = (org.huihoo.orbas.orb.types.
            ObjRefDelegate) (objectImpl._get_delegate());
        if (delegate == null) {
            //report an error
            throw new org.omg.PortableServer.POAPackage.WrongAdapter(
                "POA: Not a CORBA Object.Can NOT get delegate");
        }
        IorParser parser = delegate.getParser();

        String strObjectKey = new String(parser.getObjectKey());
        //check for right object key format
        //"poaid/objectid"
        if (strObjectKey.indexOf("/") == -1) {
            throw new org.omg.PortableServer.POAPackage.WrongAdapter(
                "POA: Malformed object key");
        }
        ObjectKey oKey = new ObjectKey(strObjectKey);
        //check for:the servant must be in this poa.
        if (!oKey.getObjectId().equals(this.id)) {
            throw new org.omg.PortableServer.POAPackage.WrongAdapter();
        }
        //
        return oKey.getObjectId();
    }

    public Servant id_to_servant(byte[] oid) throws org.omg.PortableServer.
        POAPackage.ObjectNotActive,
        org.omg.PortableServer.POAPackage.WrongPolicy {
        logger.debug(LOG_TAG, "id_to_servant(" + new String(oid) + ")");
        //check for policy first
        if (!retain && !use_default_servant) {
            throw new org.omg.PortableServer.POAPackage.WrongPolicy();
        }
        //when retian policy and servant exist
        if (retain) {
            ObjectKey oKey = new ObjectKey(this.id, oid);
            synchronized (aom) {
                if (aom.containsKey(oKey.getObjectKey())) {
                    java.lang.Object _sObj = aom.get(oKey.getObjectKey());

                    logger.debug(LOG_TAG, "object class is " +
                            _sObj.getClass().getName());
                    return (Servant) aom.get(oKey.getObjectKey());
                }
            }
        }
        else if (use_default_servant) {
            //when policy use_default_servant
            try {
                synchronized (this) {
                    if (this.get_servant() != null) {
                        return this.get_servant();
                    }
                }
            }
            catch (org.omg.PortableServer.POAPackage.NoServant exns) {
                throw new org.omg.PortableServer.POAPackage.ObjectNotActive();
            }

        }
        //
        throw new org.omg.PortableServer.POAPackage.ObjectNotActive();
    }

    public Object id_to_reference(byte[] oid) throws org.omg.PortableServer.
        POAPackage.ObjectNotActive,
        org.omg.PortableServer.POAPackage.WrongPolicy {
        logger.debug(LOG_TAG, "id_to_servant(...)");
        //check for policy first
        if (!retain) {
            throw new org.omg.PortableServer.POAPackage.WrongPolicy();
        }
        //
        ObjectKey oKey = new ObjectKey(this.id, oid);
        if (aom.containsKey(oKey.getObjectKey())) {
            try {
                return servant_to_reference( (Servant) aom.get(oKey.
                    getObjectKey()));
            }
            catch (org.omg.PortableServer.POAPackage.ServantNotActive exsna) {
                throw new org.omg.PortableServer.POAPackage.ObjectNotActive();
            }

        }
        //else throw exception
        throw new org.omg.PortableServer.POAPackage.ObjectNotActive();
    }

    public OutputStream invoke(byte[] oid, String method, InputStream is,
                               ResponseHandler handler) throws org.omg.CORBA.
        OBJECT_NOT_EXIST {
        logger.debug(LOG_TAG, "invoke(...) " + method + ", Object id is " +
                new String(oid) + ", handler class is " +
                handler.getClass().getName());
        //obtain the servant
        //ObjectKey oKey = new ObjectKey(this.id, oid);
        try {
            Servant servant
                   = id_to_servant(oid);
            String[] ids = servant._all_interfaces(this, null);
            logger.debug(LOG_TAG, "RepId is "+ids[0]);

            //invoke the servant method
            RequestProcessor processor = new RequestProcessor();
            RequestEntry entry = new RequestEntry(servant, method, is, handler);


            processor.init(this, entry);
            //process.
            processor.process();
            //return servant._invoke(method, is, handler);
            return entry.getOutputStream();
        }
        catch (org.omg.PortableServer.
               POAPackage.ObjectNotActive exena) {
            exena.printStackTrace();
            throw new org.omg.CORBA.OBJECT_NOT_EXIST();
        }
        catch (org.omg.PortableServer.POAPackage.WrongPolicy exwp) {
            exwp.printStackTrace();
            throw new org.omg.CORBA.OBJECT_NOT_EXIST();
        }
    }

    public void setOrb(ORB orb) {
        this.orb = orb;
        //for Root POA use only
        if (the_name().equals("RootPOA")) {
            orb.registerPoa(this, new String(id));
        }

    }


}